const WebSocket = require('ws');
const jwt = require('jsonwebtoken');
const { 
  JWT_SECRET, 
  WS_HEARTBEAT_INTERVAL,
  MESSAGE_TYPES,
  USER_ROLES 
} = require('../config/constants');
const DB = require('../config/mysql');

class WebSocketServer {
  constructor(server) {
    this.wss = new WebSocket.Server({ server });
    this.clients = new Map(); // 存储连接的客户端
    this.heartbeatInterval = WS_HEARTBEAT_INTERVAL;
    this.init();
  }

  init() {
    this.wss.on('connection', async (ws, req) => {
      try {
        // 验证token
        const token = req.url.split('token=')[1];
        const decoded = jwt.verify(token, JWT_SECRET);
        const userId = decoded.userId;

        // 存储连接
        this.clients.set(userId, ws);

        // 设置心跳检测
        ws.isAlive = true;
        ws.on('pong', () => {
          ws.isAlive = true;
        });

        // 获取未读消息
        const unreadMessages = await this.getUnreadMessages(userId);
        if (unreadMessages.length > 0) {
          this.sendMessage(ws, {
            type: 'unread_messages',
            data: unreadMessages
          });
        }

        // 处理消息
        ws.on('message', async (message) => {
          try {
            const data = JSON.parse(message);
            await this.handleMessage(userId, data);
          } catch (error) {
            console.error('处理消息错误:', error);
          }
        });

        // 处理连接关闭
        ws.on('close', () => {
          this.clients.delete(userId);
          this.updateUserStatus(userId, 'offline');
        });

      } catch (error) {
        console.error('WebSocket连接错误:', error);
        ws.close();
      }
    });

    // 启动心跳检测
    this.startHeartbeat();
  }

  // 心跳检测
  startHeartbeat() {
    setInterval(() => {
      this.wss.clients.forEach((ws) => {
        if (ws.isAlive === false) {
          return ws.terminate();
        }
        ws.isAlive = false;
        ws.ping();
      });
    }, this.heartbeatInterval);
  }

  // 获取未读消息
  async getUnreadMessages(userId) {
    const sql = `
      SELECT n.*, un.is_read
      FROM notifications n
      LEFT JOIN user_notifications un ON n.id = un.notification_id AND un.user_id = ?
      WHERE (un.id IS NULL OR un.is_read = 0)
      AND (n.target_type = 'all' OR 
          (n.target_type = (SELECT role_name FROM users u JOIN user_roles r ON u.role_id = r.id WHERE u.id = ?)) OR
          (n.target_id = ?))
      ORDER BY n.created_at DESC
    `;
    return await DB.query(sql, [userId, userId, userId]);
  }

  // 发送消息
  sendMessage(ws, message) {
    if (ws.readyState === WebSocket.OPEN) {
      ws.send(JSON.stringify(message));
    }
  }

  // 广播消息
  broadcast(message, filter = null) {
    this.clients.forEach((ws, userId) => {
      if (!filter || filter(userId)) {
        this.sendMessage(ws, message);
      }
    });
  }

  // 处理接收到的消息
  async handleMessage(userId, data) {
    switch (data.type) {
      case 'chat':
        // 只允许与客服聊天
        if (await this.isCustomerService(data.to)) {
          await this.handleChatMessage(userId, data);
        }
        break;
      case 'read_notification':
        await this.markNotificationAsRead(userId, data.notificationId);
        break;
      // 其他消息类型...
    }
  }

  // 检查是否是客服
  async isCustomerService(userId) {
    const sql = `
      SELECT 1 FROM users u 
      JOIN user_roles r ON u.role_id = r.id 
      WHERE u.id = ? AND r.role_name = 'customer_service'
    `;
    const result = await DB.findOne(sql, [userId]);
    return !!result;
  }

  // 处理聊天消息
  async handleChatMessage(fromUserId, data) {
    try {
      const { to: toUserId, content, msgType = 'text' } = data;

      // 检查消息接收者是否存在
      const [toUser] = await DB.query(`
        SELECT u.id, r.role_name 
        FROM users u
        JOIN user_roles r ON u.role_id = r.id
        WHERE u.id = ?
      `, [toUserId]);

      if (!toUser) {
        return this.sendMessage(this.clients.get(fromUserId), {
          type: 'error',
          message: '接收者不存在'
        });
      }

      // 保存消息记录
      await DB.query(`
        INSERT INTO chat_messages (
          from_user_id,
          to_user_id,
          content,
          msg_type,
          is_read,
          created_at
        ) VALUES (?, ?, ?, ?, false, NOW())
      `, [fromUserId, toUserId, content, msgType]);

      // 发送给接收者
      const targetWs = this.clients.get(toUserId);
      if (targetWs) {
        this.sendMessage(targetWs, {
          type: 'chat',
          from: fromUserId,
          content,
          msgType,
          timestamp: new Date().toISOString()
        });
      }

    } catch (error) {
      console.error('处理聊天消息错误:', error);
      this.sendMessage(this.clients.get(fromUserId), {
        type: 'error',
        message: '发送消息失败'
      });
    }
  }

  // 标记通知为已读
  async markNotificationAsRead(userId, notificationId) {
    const sql = `
      INSERT INTO user_notifications (user_id, notification_id, is_read, read_at)
      VALUES (?, ?, 1, NOW())
      ON DUPLICATE KEY UPDATE is_read = 1, read_at = NOW()
    `;
    await DB.query(sql, [userId, notificationId]);
  }

  // 更新用户状态
  async updateUserStatus(userId, status) {
    const sql = `
      UPDATE customer_service_status 
      SET status = ?, last_active = NOW()
      WHERE user_id = ?
    `;
    await DB.query(sql, [status, userId]);
  }
}

module.exports = WebSocketServer; 